#include <SFML/System.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>

#include <iostream>
#include <fstream>
#include <boost/lexical_cast.hpp>

#include "Engine/ResMgr.h"
#include "Engine/Map.h"

namespace CNWoofer
{
	namespace Engine
	{
		ResourceMgr::ResourceMgr( void )
		{

		}

		ResourceMgr::~ResourceMgr( void )
		{

		}
	
		void ResourceMgr::UnloadResources( int type )
		{
			std::map<std::string, Resource*>::iterator i = mResources.begin();
			
			if( type < 0 )
			{
				while( i != mResources.end() )
				{
					delete i->second->ResPtr;

					mResources.erase( i );

					i++;
				}
			}
			else
			{
				while( i != mResources.end() )
				{
					if( i->second->ResType == type )
					{
						delete i->second->ResPtr;

						mResources.erase( i );
					}

					i++;
				}
			}
		}

		void* ResourceMgr::LoadResource( std::string filename )
		{ 
			Resource* res;
			std::string ext;

			if( mResources[filename] != NULL )
			{
				return mResources[filename]->ResPtr;
			}
			else
			{
				ext = filename.substr( filename.rfind(".") + 1 );

				if( ext == "bmp" || ext == "png" )
				{
					res = new Resource;
					res->ResPtr = LoadTexture( filename );
					res->ResType = RESOURCE_TEXTURE;
				}
				else if( ext == "ttf" )
				{
					res = new Resource;
					res->ResPtr = LoadFont( filename );
					res->ResType = RESOURCE_FONT;
				}
				else if( ext == "lvl" )
				{	
					res = new Resource;
					res->ResPtr = LoadMap( filename );
					res->ResType = RESOURCE_MAP;
				}
				else if( ext == "spr" )
				{

				}
				else if( ext == "wav" )
				{
					res = new Resource;
					res->ResPtr = LoadSound( filename );
					res->ResType = RESOURCE_SOUND;
				}
			}

			if( !res->ResPtr )
			{
				std::cout << "Failed to load resource: " << filename << std::endl;

				delete res;
				return NULL;
			}

			mResources[filename] = res;

			std::cout << "Loaded resource: " << filename << std::endl;

			return mResources[filename]->ResPtr;
		}
		
		void* ResourceMgr::LoadTexture( std::string filename )
		{
			sf::Texture* tex = new sf::Texture;

			tex->loadFromFile( filename );		

			if( !tex )
			{
				delete tex;

				return NULL;
			}

			tex->setSmooth( false );

			return (void*)tex;
		}

		void* ResourceMgr::LoadFont( std::string filename )
		{
			sf::Font* font = new sf::Font;

			font->loadFromFile( filename );

			if( !font )
			{
				delete font;
				
				return NULL;
			}

			return (void*)font;
		}

		void* ResourceMgr::LoadSprite( std::string filename )
		{
			return NULL;
		}
		
		void* ResourceMgr::LoadMap( std::string filename )
		{
			Map* map = new Map;
			Tile* tile = NULL;
			std::ifstream mapfile;
			std::string buffer;
			std::map<std::string, std::string> symbols;

			mapfile.open( filename.c_str() );

			if( !mapfile.is_open() )
			{
				delete map;

				return NULL;
			}

			while( !mapfile.eof() )
			{
				mapfile >> buffer;

				if( buffer.find( "$" ) == 0 )
				{
					if( buffer.substr( 1 ) == "name" )
					{
						mapfile >> map->Name;						
					}
					else if( buffer.substr( 1 ) == "width" )
					{
						mapfile >> buffer;

						map->TilesX = boost::lexical_cast<int, std::string>( buffer );
					}
					else if( buffer.substr( 1 ) == "height" )
					{
						mapfile >> buffer;

						map->TilesY = boost::lexical_cast<int, std::string>( buffer );
					}
					else if( buffer.substr( 1 ) == "tilesize" )
					{
						mapfile >> buffer;

						map->TileSize = boost::lexical_cast<int, std::string>( buffer );
					}
					else if( buffer.substr( 1 ) == "tile" )
					{
						std::string symbol, texturename;
						
						mapfile >> symbol;
						mapfile >> texturename;

						symbols[symbol] = texturename;
					}
					else if( buffer.substr( 1 ) == "tilesbegin" )
					{
						mapfile >> buffer;

						unsigned int line = 0;

						while( buffer.find( "$" ) != 0 )
						{
							unsigned int i = 0;

							while( i < buffer.size() )
							{
								std::string symbol = buffer.substr( i, 1 );

								if( symbol != "." )
								{
									tile = new Tile;

									if( symbols[symbol] != "" )
									{
										tile->Texture = (sf::Texture*)LoadResource( symbols[symbol] );
									}

									tile->RelX = i;
									tile->RelY = line;
									tile->RealX = i * map->TileSize;
									tile->RealY = line * map->TileSize;

									map->Tiles.push_back( tile );
								}
								i++;
							}

							line++;

							mapfile >> buffer;
						}
					}
				}
			}

			std::map<std::string, std::string>::iterator i = symbols.begin();

			while( i != symbols.end() )
			{
				i++;
			}

			mapfile.close();

			return map;
		}

		void* ResourceMgr::LoadSound( std::string filename )
		{
			sf::SoundBuffer* snd = new sf::SoundBuffer;

			snd->loadFromFile( filename );

			if( !snd )
			{
				delete snd;

				return NULL;
			}

			return (void*)snd;
		}
	}
}